package cn.javaex.hgo.config.shiro;

import java.util.Collection;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.springframework.beans.factory.annotation.Autowired;

import cn.javaex.hgo.action.system.dao.hgo_menu_info.IHgoMenuInfoDAO;
import cn.javaex.hgo.action.system.dao.hgo_role_info.IHgoRoleInfoDAO;
import cn.javaex.hgo.action.system.dao.hgo_user_info.IHgoUserInfoDAO;
import cn.javaex.hgo.action.system.view.HgoUserInfo;

/**
 * 自定义realm
 * 
 * @author 陈霓清
 */
public class HgoRealm extends AuthorizingRealm {

	@Autowired
	private IHgoUserInfoDAO iHgoUserInfoDAO;
	@Autowired
	private IHgoMenuInfoDAO iHgoMenuInfoDAO;
	@Autowired
	private IHgoRoleInfoDAO iHgoRoleInfoDAO;
	@Autowired
	private EhCacheManager cacheManager;
	@Autowired
	private SessionDAO sessionDAO;
	
	/**
	 * 权限授权
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		
		HgoUserInfo userInfo = (HgoUserInfo)principals.getPrimaryPrincipal();
		
		// 查询用户的所有角色
		Set<String> roleCodeSet = iHgoRoleInfoDAO.listCodeByUserId(userInfo.getId());
		if (roleCodeSet!=null && roleCodeSet.isEmpty()==false) {
			info.addRoles(roleCodeSet);
		}
		
		// 查询用户所有的按钮权限
		Set<String> permCodeSet = iHgoMenuInfoDAO.listPermCodeByUserId(userInfo.getId());
		if (permCodeSet!=null && permCodeSet.isEmpty()==false) {
			info.addStringPermissions(permCodeSet);
		}
		
		return info;
	}

	/**
	 * 登录认证
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
		String loginName = (String)authenticationToken.getPrincipal();
		HgoUserInfo userInfo = iHgoUserInfoDAO.selectByLoginName(loginName);
		if (userInfo==null) {
			// 用户不存在
			throw new UnknownAccountException();
		}
		// 校验是否允许登录
		if (userInfo.getStatus()!=1) {
			throw new LockedAccountException();
		}
		
		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userInfo, userInfo.getPassword(), this.getName());
		return info;
	}

	/**
	 * 清除所有用户的授权缓存
	 */
	public void clearAuthorizationInfo() {
		cacheManager.getCache("cn.javaex.hgo.config.shiro.HgoRealm.authorizationCache").clear();
	}
	
	/**
	 * 清除指定用户的授权缓存
	 * @param userId 用户id
	 */
	public void clearAuthorizationInfo(String userId) {
		HgoUserInfo userInfo = iHgoUserInfoDAO.selectById(userId);
		
		if (userInfo!=null) {
			Collection<Session> sessions = sessionDAO.getActiveSessions();
			for (Session session : sessions) {
				PrincipalCollection principals = (PrincipalCollection)session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
				if (principals!=null) {
					HgoUserInfo cacheUserInfo = (HgoUserInfo)principals.getPrimaryPrincipal();
					if (userInfo.getLoginName().equals(cacheUserInfo.getLoginName())) {
						Cache<Object, Object> cache = cacheManager.getCache("cn.javaex.hgo.config.shiro.HgoRealm.authorizationCache");
						cache.remove(new SimplePrincipalCollection(cacheUserInfo, this.getName()));
						break;
					}
				}
			}
		}
	}
}
